package com.atguigu.gmall.cart.service.impl;

import com.atguigu.gmall.cart.service.CartService;
import com.atguigu.gmall.common.constant.RedisConst;
import com.atguigu.gmall.common.util.DateUtil;
import com.atguigu.gmall.model.cart.CartInfo;
import com.atguigu.gmall.model.product.SkuInfo;
import com.atguigu.gmall.product.client.ProductFeignClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.BoundHashOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.util.*;
import java.util.stream.Collectors;

@Service
public class CartServiceImpl implements CartService {

    @Autowired
    private RedisTemplate redisTemplate;

    @Autowired
    private ProductFeignClient productFeignClient;

    @Override
    public void addToCart(Long skuId, Integer skuNum, String userId) {
        /*
        1.	购物车中没有这个商品，直接加入购物车！
        2.	购物车中有这个商品，则数量相加！
        3.	添加购物车时，这个商品默认是选中的！
        4.	添加购物车的时候，这个商品的价格应该是实时价格！
        5.	每次添加的时候，注意要修改更新时间！
         */
        //  声明一个购物车的key = user:userId:cart
        String cartKey = getCartKey(userId);
        //  hget key field; cartInfoExist.isChecked = 0;
        CartInfo cartInfoExist = (CartInfo) this.redisTemplate.opsForHash().get(cartKey, skuId.toString());

        //  BoundHashOperations<H, HK, HV>  hset key field value;
        //        BoundHashOperations<String,String,CartInfo> boundHashOperations = this.redisTemplate.boundHashOps(cartKey);
        //
        //        if (boundHashOperations.hasKey(skuId.toString())) {
        //
        //        }
        if (cartInfoExist!=null){
            //  有数据：
            cartInfoExist.setSkuNum(cartInfoExist.getSkuNum()+skuNum);
            //  cartInfoExist.getIsChecked(); 都是默认选中.
            //            if (cartInfoExist.getIsChecked().intValue()==0){
            //                cartInfoExist.setIsChecked(1);
            //            }
            cartInfoExist.setIsChecked(1);
            //  赋值实时价格：
            cartInfoExist.setSkuPrice(productFeignClient.getSkuPrice(skuId));
            //  设置更新时间.
            cartInfoExist.setUpdateTime(new Date());

            //  this.redisTemplate.opsForHash().put(cartKey,skuId.toString(),cartInfoExist);
        } else {
            //    购物车中没有这个商品！
            SkuInfo skuInfo = productFeignClient.getSkuInfo(skuId);
            cartInfoExist = new CartInfo();
            cartInfoExist.setSkuId(skuId);
            cartInfoExist.setSkuName(skuInfo.getSkuName());
            cartInfoExist.setSkuNum(skuNum);
            //  加入购物车时的价格 有可能会出现数据不一致.
            //  cartInfoExist.setCartPrice(skuInfo.getPrice());
            cartInfoExist.setCartPrice(this.productFeignClient.getSkuPrice(skuId));
            //  实时价格
            cartInfoExist.setSkuPrice(this.productFeignClient.getSkuPrice(skuId));
            cartInfoExist.setUserId(userId);
            cartInfoExist.setImgUrl(skuInfo.getSkuDefaultImg());

            //  查询的时候：必须按照更新时间进行排序!
            cartInfoExist.setCreateTime(new Date());
            cartInfoExist.setUpdateTime(new Date());
            //  this.redisTemplate.opsForHash().put(cartKey,skuId.toString(),cartInfoExist);
        }
        //  写回缓存. hset key field value;
        this.redisTemplate.opsForHash().put(cartKey,skuId.toString(),cartInfoExist);
        //  思考的问题！购物车列表是否有过期时间?
        //  没有：买足够的内存空间.  有：过期时间是多少? 登录：180天 身份：购买力 50W; 20w 2年 未登录：30天;

    }

    @Override
    public List<CartInfo> getCartList(String userId, String userTempId) {
        /*
        1.  简单查看：二选一：
                不考虑合并的情况！
                登录：userId
                未登录：userTempId

         2. 考虑合并购车
                什么情况下才能合并?
                    userId != null and 临时购物车有数据！ 才会发生合并！
                合并之后删除临时购物车数据！
         */
        //  声明购车列表集合
        List<CartInfo> cartInfoNoLoginList = new ArrayList<>();
        //  判断未登录用户Id.
        if (!StringUtils.isEmpty(userTempId)){
            //  获取未登录购物车数据.
            String cartKey = this.getCartKey(userTempId);
            //  获取数据
            cartInfoNoLoginList = this.redisTemplate.opsForHash().values(cartKey);

        }

        //  判断用户Id 是否存在！ 不用想合并！
        if (StringUtils.isEmpty(userId)){
            if (!CollectionUtils.isEmpty(cartInfoNoLoginList)){
                cartInfoNoLoginList.sort((cartInfo1,cartInfo2)->{
                    //  按照时间降序排列
                    return DateUtil.truncatedCompareTo(cartInfo2.getUpdateTime(),cartInfo1.getUpdateTime(), Calendar.SECOND);
                });
            }
            return cartInfoNoLoginList;
        }
        //  声明一个登录购物车集合
        List<CartInfo> cartInfoLoginList = new ArrayList<>();
        //  判断用户登录时：
        if (!StringUtils.isEmpty(userId)){
            //  获取登录购物车的key
            String cartKey = this.getCartKey(userId);
            //  根据key 来获取数据.
            BoundHashOperations<String,String,CartInfo> boundHashOperations = this.redisTemplate.boundHashOps(cartKey);
            //  boundHashOperations.values() ; // hvals key;
            //  boundHashOperations.get();  hget key field;
            //  boundHashOperations.put();  hset key field value;
            //  boundHashOperations.hasKey(); 是否包含field
            //  才有可能发生合并.
            //  发生合并！
            if (!CollectionUtils.isEmpty(cartInfoNoLoginList)){
                //  遍历未登录购物车集合.
                cartInfoNoLoginList.forEach(cartInfoNoLogin -> {
                    //  判断  hget key field ; 17 ，18
                    if (boundHashOperations.hasKey(cartInfoNoLogin.getSkuId().toString())){
                        //  skuId 相同合并购物车. 未登录---> 登录！
                        CartInfo cartInfoLogin = boundHashOperations.get(cartInfoNoLogin.getSkuId().toString());
                        //  商品的数量相加
                        cartInfoLogin.setSkuNum(cartInfoLogin.getSkuNum()+cartInfoNoLogin.getSkuNum());
                        //  更新时间
                        cartInfoLogin.setUpdateTime(new Date());
                        //  选中状态. 未登录选中了.
                        if (cartInfoNoLogin.getIsChecked().intValue()==1){
                            //  登录的时候，是未选中.
                            if (cartInfoLogin.getIsChecked().intValue()==0){
                                cartInfoLogin.setIsChecked(1);
                            }
                        }
                        //  查询最新价格：
                        //  cartInfoLogin.setSkuPrice(this.productFeignClient.getSkuPrice(cartInfoNoLogin.getSkuId()));
                        //  hset key field value;
                        boundHashOperations.put(cartInfoNoLogin.getSkuId().toString(),cartInfoLogin);
                    } else {
                        //                        if (cartInfoNoLogin.getIsChecked().intValue()==1){
                        //                            //  未登录userId 变userId 19
                        //                            cartInfoNoLogin.setUserId(userId);
                        //                            //  选中状态; 最新价格; 可选.
                        //                            cartInfoNoLogin.setUpdateTime(new Date());
                        //                            cartInfoNoLogin.setCreateTime(new Date());
                        //                            //  将没有的商品数据添加到redis.
                        //                            boundHashOperations.put(cartInfoNoLogin.getSkuId().toString(),cartInfoNoLogin);
                        //                        }

                        //  未登录userId 变userId 19;
                        cartInfoNoLogin.setUserId(userId);
                        //  选中状态; 最新价格; 可选.
                        cartInfoNoLogin.setUpdateTime(new Date());
                        cartInfoNoLogin.setCreateTime(new Date());
                        //  将没有的商品数据添加到redis.
                        boundHashOperations.put(cartInfoNoLogin.getSkuId().toString(),cartInfoNoLogin);
                    }
                });
                //  删除未登录购物车集合.
                this.redisTemplate.delete(this.getCartKey(userTempId));
            }
            //  获取登录购物车集合; 包含了合并之后的，同时也包含未合并的！
            cartInfoLoginList = boundHashOperations.values();
        }
        //  判断集合
        if (CollectionUtils.isEmpty(cartInfoLoginList)){
            return new ArrayList<>();
        }
        //  排序.
        cartInfoLoginList.sort((cartInfo1,cartInfo2)->{
            //  按照时间降序排列
            return DateUtil.truncatedCompareTo(cartInfo2.getUpdateTime(),cartInfo1.getUpdateTime(), Calendar.SECOND);
        });
        //  返回数据
        return cartInfoLoginList;
    }

    @Override
    public void checkCart(Long skuId, Integer isChecked, String userId) {
        //  获取购物车的key
        String cartKey = this.getCartKey(userId);
        //  hget key field;
        CartInfo cartInfo = (CartInfo) this.redisTemplate.opsForHash().get(cartKey, skuId.toString());
        if (cartInfo!=null){
            cartInfo.setIsChecked(isChecked);
        }
        //  写回缓存. hset key field value;
        this.redisTemplate.opsForHash().put(cartKey,skuId.toString(),cartInfo);
    }

    @Override
    public void allCheckCart(Integer isChecked, String userId) {
        //  获取到购物车的key
        String cartKey = this.getCartKey(userId);
        //  获取到所有购物车列表. hvals key;
        List<CartInfo> cartInfoList = this.redisTemplate.opsForHash().values(cartKey);
        //  判断
        //        if (!CollectionUtils.isEmpty(cartInfoList)){
        //            cartInfoList.forEach(cartInfo -> {
        //                cartInfo.setIsChecked(isChecked);
        //                //  hset key field value;
        //                this.redisTemplate.opsForHash().put(cartKey,cartInfo.getSkuId().toString(),cartInfo);
        //            });
        //        }
        //  HashMap<String, Objects> map = new HashMap<>();
        if (!CollectionUtils.isEmpty(cartInfoList)){
            //  stream 流；
            Map<String, CartInfo> infoMap = cartInfoList.stream().map(cartInfo -> {
                cartInfo.setIsChecked(isChecked);
                return cartInfo;
            }).collect(Collectors.toMap((cartInfo -> cartInfo.getSkuId().toString()), (cartInfo -> cartInfo)));
            // 写回去！ hmset key map; map = field value;
            this.redisTemplate.opsForHash().putAll(cartKey,infoMap);
        }
    }

    @Override
    public void deleteCart(Long skuId, String userId) {
        //  hdel key field;
        //  获取到购物车key
        String cartKey = this.getCartKey(userId);
        //  直接删除
        this.redisTemplate.opsForHash().delete(cartKey,skuId.toString());

    }

    @Override
    public void clearCart(String userId) {
        //  获取购物车的key
        String cartKey = this.getCartKey(userId);
        //  删除购物车.
        this.redisTemplate.delete(cartKey);
    }

    @Override
    public List<CartInfo> getCartCheckedList(String userId) {
        //  获取到购物车的key
        String cartKey = this.getCartKey(userId);
        //  获取到购物车中的所有数据 havls key ;
        List<CartInfo> cartInfoList = this.redisTemplate.opsForHash().values(cartKey);

        //        ArrayList<CartInfo> cartInfoListChecked = new ArrayList<>();
        //        if (!CollectionUtils.isEmpty(cartInfoList)){
        //            cartInfoList.forEach(cartInfo -> {
        //                if (cartInfo.getIsChecked().intValue()==1){
        //                    cartInfoListChecked.add(cartInfo);
        //                }
        //            });
        //        }

        //  过滤filter:
        if (!CollectionUtils.isEmpty(cartInfoList)){
            //   boolean test(T t);
            List<CartInfo> infoList = cartInfoList.stream().filter(cartInfo -> cartInfo.getIsChecked().intValue() == 1).collect(Collectors.toList());
            //  获取选中的购物项
            return infoList;
        }
        return null;
    }

    private String getCartKey(String userId) {
       return RedisConst.USER_KEY_PREFIX+ userId +RedisConst.USER_CART_KEY_SUFFIX;
    }

    public static void main(String[] args) {
        List<Integer> list = Arrays.asList(1, 4, 2, 6, 5);
        list.sort((o1,o2)-> o1-o2);
        System.out.println(list);
    }


}
